package net.fornwall.eclipsecoder.csharpsupport;

import java.io.ByteArrayInputStream;

import net.fornwall.eclipsecoder.languages.LanguageSupport;
import net.fornwall.eclipsecoder.stats.CodeGenerator;
import net.fornwall.eclipsecoder.stats.ProblemStatement;
import net.fornwall.eclipsecoder.util.Utilities;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.emonic.base.Constants;
import org.emonic.base.FileManipulators.BuildfileManipulatorFactory;
import org.emonic.base.FileManipulators.IBuildfileManipulator;
import org.emonic.base.FileManipulators.ProjectPreferencesManipulator;

public class CSharpLanguageSupport extends LanguageSupport {

	@Override
	protected CodeGenerator createCodeGenerator(ProblemStatement problemStatement) {
		return new CSharpCodeGenerator(problemStatement);
	}

	@Override
	protected IFile createLanguageProject(final IProject project) throws Exception {
		// see EmonoNewProjectResourceWizard.java
		IWorkspace workspace = ResourcesPlugin.getWorkspace();

		// problem statement and tests
		IFile testsFile = null;
		String testsFileName = getProblemStatement().getSolutionClassName() + "Test.cs";
		testsFile = project.getFile(testsFileName);
		testsFile.create(new ByteArrayInputStream(getCodeGenerator().getTestsSource().getBytes()), false, null);
		IFile sourceFile = project.getFile(getSolutionFileName());
		sourceFile.create(new ByteArrayInputStream(getInitialSource().getBytes()), true, null);

		// add nature
		IProjectDescription newProjectDescription = workspace.newProjectDescription(project.getName());
		newProjectDescription.setNatureIds(new String[] { Constants.EmonicNatureID });
		project.setDescription(newProjectDescription, null);

		// create prefs file
		String copyright = "";
		String namespace = "";
		String buildMechanism = CSharpSupportPlugIn.getInstance().getBuildSystem();
		String buildFile = "build.xml";
		ProjectPreferencesManipulator prefsManipulator = new ProjectPreferencesManipulator(project);
		prefsManipulator.setPrefs(copyright, namespace, buildMechanism, buildFile);
		prefsManipulator.write();

		// create build file
		IFile fn = project.getFile(buildFile);
		IBuildfileManipulator buildFM = BuildfileManipulatorFactory.createBFM(fn, new NullProgressMonitor());
		buildFM.setProject(project.getName());
		buildFM.addTarget(Constants.DefaultTaskName);
		buildFM.addPropertyInProject("src", ".");
		// bug in emonic: requires bin folder for build, see
		// NAntBuildFileManipulator.java:
		project.getFolder("bin").create(true, true, new NullProgressMonitor());
		buildFM.addPropertyInProject("build", "bin");
		buildFM.setTargetFramework(CSharpSupportPlugIn.getInstance().getTargetFramework());

		String targetName = project.getName().toLowerCase();
		String targetType = "exe";
		final String targetFile = targetName + "." + targetType;
		String folderPath = ".";
		String fileName = getSolutionFileName();
		boolean optimizeCode = true;
		boolean debugCode = true;
		String warnLevel = "4";
		String references = "";
		String defines = "";
		String supportedLanguage = IBuildfileManipulator.CSHARP_LANGUAGE;
		buildFM.addOrModifyLanguageTarget(targetName, folderPath, fileName, targetType, optimizeCode, debugCode,
				warnLevel, references, defines, supportedLanguage);
		buildFM.addToExistingLanguageTarget(targetName, folderPath, testsFileName, supportedLanguage);
		buildFM.write();

		Utilities.buildAndRun(project, new CSharpLauncher(project.getFolder("bin").getFile(targetFile)));

		return sourceFile;
	}

	@Override
	protected String getCodeEditorID() {
		return "org.emonic.base.editors.CSharpEditor";
	}

	@Override
	protected String getCodeTemplate() {
		return CSharpSupportPlugIn.getInstance().getCodeTemplate();
	}

	@Override
	public String getLanguageName() {
		return LanguageSupport.LANGUAGE_NAME_CSHARP;
	}

	@Override
	public String getPerspectiveID() {
		return "org.emonic.base.emonicperspective";
	}

	@Override
	protected String getSolutionFileName() {
		return getProblemStatement().getClassName() + ".cs";
	}
}
